<template>
  <div class="menu-container">
    <el-card class="box-card">
      <!-- 搜索区域 -->
      <search-form
        v-model="queryParams"
        @search="handleQuery"
        @reset="handleReset"
      >
        <el-form-item label="菜单名称">
          <el-input
            v-model="queryParams.title"
            placeholder="请输入菜单名称"
            clearable
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="状态">
          <el-select
            v-model="queryParams.status"
            placeholder="请选择状态"
            clearable
          >
            <el-option label="显示" value="1" />
            <el-option label="隐藏" value="0" />
          </el-select>
        </el-form-item>
      </search-form>

      <!-- 操作按钮区域 -->
      <div class="toolbar">
        <el-button type="primary" :icon="Plus" @click="handleAdd">新增</el-button>
        <el-button type="success" :icon="RefreshRight" @click="handleRefresh">刷新</el-button>
      </div>

      <!-- 表格区域 -->
      <el-table
        v-loading="loading"
        :data="menuList"
        row-key="id"
        :tree-props="{ children: 'children' }"
        :height="tableHeight"
      >
        <el-table-column label="菜单名称" prop="title" show-overflow-tooltip>
          <template #default="{ row }">
            <el-icon v-if="row.meta?.icon" class="menu-icon">
              <component :is="row.meta.icon" />
            </el-icon>
            <span>{{ row.title }}</span>
          </template>
        </el-table-column>
        <el-table-column label="路由路径" prop="path" />
        <el-table-column
          label="组件路径"
          prop="component"
          show-overflow-tooltip
        />
        <el-table-column
          label="权限标识"
          prop="permission"
          show-overflow-tooltip
        />
        <el-table-column label="排序" prop="sort" width="80" align="center" />
        <el-table-column label="类型" align="center" width="80">
          <template #default="{ row }">
            <el-tag v-if="row.type === 0" type="primary">目录</el-tag>
            <el-tag v-else-if="row.type === 1" type="success">菜单</el-tag>
            <el-tag v-else type="info">按钮</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="状态" align="center" width="80">
          <template #default="{ row }">
            <el-tag :type="row.status === '1' ? 'success' : 'danger'">
              {{ row.status === "1" ? "显示" : "隐藏" }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="220" align="center" fixed="right">
          <template #default="{ row }">
            <el-button
              type="primary"
              link
              :icon="Plus"
              v-if="row.type !== 2"
              @click="handleAdd(row)"
            >
              新增
            </el-button>
            <el-button
              type="primary"
              link
              :icon="Edit"
              @click="handleUpdate(row)"
            >
              编辑
            </el-button>
            <el-button
              type="danger"
              link
              :icon="Delete"
              @click="handleDelete(row)"
              v-if="!hasChildren(row)"
            >
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 菜单表单对话框 -->
    <el-dialog
      v-model="dialog.visible"
      :title="dialog.title"
      width="600px"
      append-to-body
      @close="resetForm"
    >
      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
        <el-form-item label="上级菜单">
          <el-tree-select
            v-model="form.parentId"
            :data="menuOptions"
            :props="{ label: 'title', value: 'id', children: 'children' }"
            placeholder="请选择上级菜单"
            check-strictly
            :render-after-expand="false"
          />
        </el-form-item>
        <el-form-item label="菜单类型" required>
          <el-radio-group v-model="form.type">
            <el-radio :value="0">目录</el-radio>
            <el-radio :value="1">菜单</el-radio>
            <el-radio :value="2">按钮</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单名称" prop="title">
          <el-input v-model="form.title" placeholder="请输入菜单名称" />
        </el-form-item>
        <el-form-item label="路由路径" prop="path" v-if="form.type !== 2">
          <el-input v-model="form.path" placeholder="请输入路由路径" />
        </el-form-item>
        <el-form-item label="组件路径" prop="component" v-if="form.type === 1">
          <el-input v-model="form.component" placeholder="请输入组件路径" />
        </el-form-item>
        <el-form-item label="权限标识" prop="permission" v-if="form.type === 2">
          <el-input v-model="form.permission" placeholder="请输入权限标识" />
        </el-form-item>
        <el-form-item label="菜单图标" v-if="form.type !== 2">
          <el-input v-model="form.icon" placeholder="请选择图标" readonly>
            <template #prepend>
              <el-icon v-if="form.icon">
                <component :is="form.icon" />
              </el-icon>
            </template>
            <template #append>
              <el-button @click="openIconSelect">
                选择图标
              </el-button>
            </template>
          </el-input>
        </el-form-item>
        <el-form-item label="排序" prop="sort">
          <el-input-number v-model="form.sort" :min="0" :max="999" />
        </el-form-item>
        <el-form-item label="状态">
          <el-radio-group v-model="form.status">
            <el-radio :value="'1'">显示</el-radio>
            <el-radio :value="'0'">隐藏</el-radio>
          </el-radio-group>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialog.visible = false">取 消</el-button>
          <el-button type="primary" @click="submitForm">确 定</el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 图标选择器对话框 -->
    <el-dialog
      v-model="iconDialog.visible"
      title="选择图标"
      width="600px"
      append-to-body
      destroy-on-close
    >
      <div class="icon-container">
        <!-- 搜索框 -->
        <div class="icon-search">
          <el-input
            v-model="iconDialog.keyword"
            placeholder="搜索图标"
            clearable
            @input="filterIcons"
          >
            <template #prefix>
              <el-icon><Search /></el-icon>
            </template>
          </el-input>
        </div>

        <!-- 图标列表 -->
        <el-scrollbar height="500px">
          <div class="icon-list">
            <div
              v-for="icon in filteredIconList"
              :key="icon"
              class="icon-item"
              :class="{ active: form.icon === icon }"
              @click="handleSelectIcon(icon)"
            >
              <div class="icon-preview">
                <el-icon>
                  <component :is="icon" />
                </el-icon>
              </div>
              <div class="icon-info">
                <span class="icon-name">{{ icon }}</span>
              </div>
            </div>
          </div>
        </el-scrollbar>
      </div>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount } from "vue";
import { Plus, Edit, Delete, RefreshRight, Search } from "@element-plus/icons-vue";
import * as ElementPlusIconsVue from "@element-plus/icons-vue";
import { ElMessage, ElMessageBox } from "element-plus";
import { getMenuTree, addMenu, updateMenu, deleteMenu } from "@/api/system/menu";
import SearchForm from "@/components/base/SearchForm.vue";

// 表单校验规则
const rules = {
  title: [{ required: true, message: "请输入菜单名称", trigger: "blur" }],
  path: [
    { required: true, message: "请输入路由路径", trigger: "blur" },
  ],
  component: [
    { required: true, message: "请输入组件路径", trigger: "blur" },
    { pattern: /^[A-Za-z]/, message: "组件路径必须以字母开头", trigger: "blur" },
  ],
  permission: [
    { required: true, message: "请输入权限标识", trigger: "blur" },
    { 
      pattern: /^[a-z]+:[a-z]+:[a-z]+$/,
      message: "权限标识格式为 模块:菜单:操作",
      trigger: "blur"
    },
  ],
  sort: [
    { required: true, message: "请输入排序", trigger: "blur" },
    { type: "number", message: "排序必须为数字", trigger: "blur" },
  ],
};

// 查询参数
const queryParams = ref({
  title: "",
  status: "",
});

// 表格数据
const loading = ref(false);
const menuList = ref([]);
const tableHeight = ref(500);

// 表单对话框
const dialog = reactive({
  visible: false,
  title: "",
  type: "",
});

// 表单数据
const formRef = ref();
const form = reactive({
  id: undefined,
  parentId: 0,
  type: 0,
  title: "",
  path: "",
  component: "",
  permission: "",
  icon: "",
  sort: 0,
  status: "1",
  meta: {
    title: "",
    icon: ""
  }
});

// 菜单树选项
const menuOptions = ref([]);

// 图标选择器
const iconDialog = reactive({
  visible: false,
  keyword: "",
});
const iconList = Object.keys(ElementPlusIconsVue).filter(
  (key) => key !== "default"
);

// 过滤后的图标列表
const filteredIconList = ref(iconList);

// 过滤图标
const filterIcons = () => {
  if (!iconDialog.keyword) {
    filteredIconList.value = iconList;
  } else {
    const keyword = iconDialog.keyword.toLowerCase();
    filteredIconList.value = iconList.filter(icon => 
      icon.toLowerCase().includes(keyword)
    );
  }
};

// 获取菜单列表
const getList = async () => {
  loading.value = true;
  try {
    const { data } = await getMenuTree();
    // 处理菜单数据
    const processMenus = (menus: Menu[]): Menu[] => {
      return menus.map(menu => ({
        ...menu,
        title: menu.title || menu.name,
        meta: {
          title: menu.title || menu.name,
          icon: menu.icon
        },
        children: menu.children ? processMenus(menu.children) : undefined
      }));
    };
    
    menuList.value = processMenus(data);
    menuOptions.value = [{ id: 0, title: "顶级菜单", children: menuList.value }];
  } catch (error: any) {
    ElMessage.error(error.message || "获取菜单列表失败");
  } finally {
    loading.value = false;
  }
};

// 查询操作
const handleQuery = () => {
  getList();
};

// 重置查询
const handleReset = () => {
  queryParams.value.title = "";
  queryParams.value.status = "";
  handleQuery();
};

// 新增菜单
const handleAdd = (row?: any) => {
  dialog.type = "add";
  dialog.title = "新增菜单";
  dialog.visible = true;
  form.id = undefined;
  form.parentId = row?.id || 0;
  form.type = row?.type === 0 ? 1 : row?.type === 1 ? 2 : 0;
  form.title = "";
  form.path = "";
  form.component = "";
  form.permission = "";
  form.icon = "";
  form.sort = 0;
  form.status = "1";
};

// 修改菜单
const handleUpdate = (row: any) => {
  dialog.type = "update";
  dialog.title = "修改菜单";
  dialog.visible = true;
  Object.assign(form, row);
};

// 提交表单
const submitForm = async () => {
  if (!formRef.value) return;

  try {
    await formRef.value.validate();
    const params = {
      ...form,
      title: form.title,
      name: form.title,
      meta: {
        title: form.title,
        icon: form.icon
      }
    };
    
    console.log('Submit menu data:', params);
    
    if (dialog.type === "add") {
      await addMenu(params);
    } else {
      await updateMenu(params);
    }
    ElMessage.success(dialog.type === "add" ? "新增成功" : "修改成功");
    dialog.visible = false;
    getList();
  } catch (error: any) {
    console.error('Submit menu error:', error);
    ElMessage.error(
      error.message || (dialog.type === "add" ? "新增失败" : "修改失败")
    );
  }
};

// 删除菜单
const handleDelete = async (row: any) => {
  try {
    await ElMessageBox.confirm(
      '是否确认删除名称为"' + row.title + '"的菜单项？',
      "提示",
      {
        type: "warning",
      }
    );
    await deleteMenu(row.id);
    ElMessage.success("删除成功");
    getList();
  } catch (error: any) {
    if (error !== "cancel") {
      ElMessage.error(error.message || "删除失败");
    }
  }
};

// 打开图标选择器
const openIconSelect = () => {
  iconDialog.visible = true;
};

// 选择图标
const handleSelectIcon = (icon: string) => {
  form.icon = icon;
  iconDialog.visible = false;
};

// 计算表格高度
const calculateTableHeight = () => {
  const windowHeight = window.innerHeight;
  const otherHeight = 300; // 预估其他元素的总高度
  tableHeight.value = windowHeight - otherHeight;
};

// 检查是否有子节点
const hasChildren = (row: any) => {
  return row.children && row.children.length > 0;
};

// 刷新列表
const handleRefresh = () => {
  getList();
};

// 重置表单
const resetForm = () => {
  if (formRef.value) {
    formRef.value.resetFields();
  }
  Object.assign(form, {
    id: undefined,
    parentId: 0,
    type: 0,
    title: "",
    path: "",
    component: "",
    permission: "",
    icon: "",
    sort: 0,
    status: "1",
    meta: {
      title: "",
      icon: ""
    }
  });
};

// 复制图标名称
const copyIconName = async (icon: string) => {
  try {
    await navigator.clipboard.writeText(icon);
    ElMessage.success('复制成功');
  } catch (err) {
    ElMessage.error('复制失败');
  }
};

// 确认选择图标
const confirmSelectIcon = () => {
  if (!form.icon) return;
  iconDialog.visible = false;
};

onMounted(() => {
  getList();
  calculateTableHeight();
  window.addEventListener("resize", calculateTableHeight);
});

onBeforeUnmount(() => {
  window.removeEventListener("resize", calculateTableHeight);
});
</script>

<style lang="scss" scoped>
.menu-container {
  height: 100%;

  .box-card {
    height: 100%;
    display: flex;
    flex-direction: column;

    :deep(.el-card__body) {
      flex: 1;
      overflow: hidden;
      display: flex;
      flex-direction: column;
    }
  }

  .menu-icon {
    margin-right: 8px;
    font-size: 16px;
  }

  .toolbar {
    margin-bottom: 16px;
    display: flex;
    gap: 8px;
  }

  .icon-container {
    display: flex;
    flex-direction: column;
    height: 600px;
    
    .icon-search {
      padding: 0 20px 16px;
      border-bottom: 1px solid var(--el-border-color-lighter);
    }

    .icon-list {
      flex: 1;
      overflow-y: auto;
      padding: 20px;
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
      gap: 16px;
      
      .icon-item {
        display: flex;
        flex-direction: column;
        align-items: center;
        padding: 16px;
        cursor: pointer;
        border-radius: 8px;
        border: 1px solid var(--el-border-color-lighter);
        transition: all 0.3s ease;

        &:hover {
          transform: translateY(-2px);
          box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
          border-color: var(--el-color-primary-light-5);
        }

        &.active {
          background-color: var(--el-color-primary-light-9);
          border-color: var(--el-color-primary);
        }

        .icon-preview {
          width: 48px;
          height: 48px;
          display: flex;
          align-items: center;
          justify-content: center;
          margin-bottom: 12px;
          border-radius: 8px;
          background-color: var(--el-color-primary-light-9);

          .el-icon {
            font-size: 24px;
            color: var(--el-color-primary);
          }
        }

        .icon-info {
          width: 100%;
          text-align: center;

          .icon-name {
            display: block;
            font-size: 13px;
            color: var(--el-text-color-regular);
            margin-bottom: 8px;
            word-break: break-all;
          }
        }
      }
    }

    .icon-footer {
      padding: 16px 20px;
      border-top: 1px solid var(--el-border-color-lighter);
      display: flex;
      justify-content: flex-end;
      gap: 12px;
    }
  }
}

// 优化滚动条样式
::-webkit-scrollbar {
  width: 6px;
  height: 6px;
}

::-webkit-scrollbar-thumb {
  border-radius: 3px;
  background-color: var(--el-border-color);
  
  &:hover {
    background-color: var(--el-border-color-darker);
  }
}

::-webkit-scrollbar-track {
  border-radius: 3px;
  background-color: transparent;
}

// 响应式布局优化
@media screen and (max-width: 768px) {
  .menu-container {
    .icon-container {
      height: 500px;
      
      .icon-list {
        grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
        gap: 12px;
        padding: 12px;
        
        .icon-item {
          padding: 12px;
          
          .icon-preview {
            width: 40px;
            height: 40px;
            margin-bottom: 8px;
            
            .el-icon {
              font-size: 20px;
            }
          }
          
          .icon-info {
            .icon-name {
              font-size: 12px;
              margin-bottom: 6px;
            }
          }
        }
      }
    }
  }
}

.icon-container {
  .icon-search {
    margin-bottom: 16px;
  }

  .icon-list {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
    gap: 12px;
    padding: 12px;
    
    .icon-item {
      display: flex;
      flex-direction: column;
      align-items: center;
      padding: 12px 8px;
      cursor: pointer;
      border-radius: 4px;
      border: 1px solid var(--el-border-color-lighter);
      transition: all 0.2s ease;

      &:hover {
        background-color: var(--el-color-primary-light-9);
        border-color: var(--el-color-primary-light-7);
        transform: translateY(-2px);
      }

      &.active {
        background-color: var(--el-color-primary-light-8);
        border-color: var(--el-color-primary);
      }

      .icon-preview {
        width: 32px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-bottom: 8px;

        .el-icon {
          font-size: 20px;
          color: var(--el-color-primary);
        }
      }

      .icon-info {
        width: 100%;
        text-align: center;

        .icon-name {
          font-size: 12px;
          color: var(--el-text-color-secondary);
          word-break: break-all;
          display: -webkit-box;
          -webkit-line-clamp: 2;
          -webkit-box-orient: vertical;
          overflow: hidden;
        }
      }
    }
  }
}

// 响应式布局优化
@media screen and (max-width: 768px) {
  .icon-container {
    .icon-list {
      grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
      gap: 8px;
      padding: 8px;
      
      .icon-item {
        padding: 8px;
        
        .icon-preview {
          width: 28px;
          height: 28px;
          margin-bottom: 6px;
          
          .el-icon {
            font-size: 18px;
          }
        }
        
        .icon-info {
          .icon-name {
            font-size: 11px;
          }
        }
      }
    }
  }
}
</style>
